﻿namespace ImageProcessing
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    using ImageProcessing;

    /// <summary>
    /// Form Class to represent the image
    /// </summary>
    public partial class PicForm : Form
    {
        /// <summary>
        /// Shape of the cursor
        /// </summary>
        private static CursorType curso = CursorType.Default;

        /// <summary>
        /// Mode of the image editing 
        /// </summary>
        private static PicMode mode = PicMode.Default;

        /// <summary>
        /// Selected rectangle
        /// </summary>
        private Rectangle rect;

        /// <summary>
        /// Point of the selected rectangle and Cursor
        /// </summary>
        private Point topLeft, downRight, cursorCurrPos, cursorStartPos;

        /// <summary>
        /// The displayed image object.
        /// </summary>
        private DImage dimage;

        /// <summary>
        /// Initializes a new instance of the <see cref="PicForm"/> class.
        /// </summary>
        /// <param name="di">The di.</param>
        public PicForm(ref DImage di)
        {
            this.InitializeComponent();
            this.dimage = di;
            Bitmap image = new Bitmap(di.FilePath);
            this.BackgroundImage = image;
            this.UpdateSize();
            this.DoubleBuffered = true;
            this.cursorCurrPos.X = this.cursorCurrPos.Y = this.cursorStartPos.X = this.cursorStartPos.Y = 0;
            this.StartPosition = FormStartPosition.CenterParent;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PicForm"/> class.
        /// </summary>
        /// <param name="di">The di.</param>
        public PicForm(DImage di)
        {
            this.InitializeComponent();
            this.dimage = di;
            this.BackgroundImage = di.ImageBitmap;
            this.Text = di.Name;
            this.Size = new Size(this.BackgroundImage.Size.Width + 15, this.BackgroundImage.Size.Height + 40);
            this.DoubleBuffered = true;
            this.cursorCurrPos.X = this.cursorCurrPos.Y = this.cursorStartPos.X = this.cursorStartPos.Y = 0;
            this.StartPosition = FormStartPosition.CenterParent;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PicForm"/> class.
        /// </summary>
        public PicForm()
        {
            this.InitializeComponent();
            this.BackColor = Color.White;
            this.DoubleBuffered = true;
            this.cursorCurrPos.X = this.cursorCurrPos.Y = this.cursorStartPos.X = this.cursorStartPos.Y = 0;
        }

        /// <summary>
        /// Gets or sets the mode1.
        /// </summary>
        /// <value>
        /// The mode1.
        /// </value>
        public static PicMode Mode1
        {
            get { return PicForm.mode; }
            set { PicForm.mode = value; }
        }

        /// <summary>
        /// Gets or sets the curso1.
        /// </summary>
        /// <value>
        /// The curso1.
        /// </value>
        public static CursorType Curso1
        {
            get { return PicForm.curso; }
            set { PicForm.curso = value; }
        }

        /// <summary>
        /// Gets or sets the cursor start pos.
        /// </summary>
        /// <value>
        /// The cursor start pos.
        /// </value>
        public Point CursorStartPos
        {
            get { return this.cursorStartPos; }
            set { this.cursorStartPos = value; }
        }

        /// <summary>
        /// Gets or sets the cursor curr pos.
        /// </summary>
        /// <value>
        /// The cursor curr pos.
        /// </value>
        public Point CursorCurrPos
        {
            get { return this.cursorCurrPos; }
            set { this.cursorCurrPos = value; }
        }

        /// <summary>
        /// Gets or sets down right.
        /// </summary>
        /// <value>
        /// Down right.
        /// </value>
        public Point DownRight
        {
            get { return this.downRight; }
            set { this.downRight = value; }
        }

        /// <summary>
        /// Gets or sets up left.
        /// </summary>
        /// <value>
        /// Up left.
        /// </value>
        public Point UpLeft
        {
            get { return this.topLeft; }
            set { this.topLeft = value; }
        }

        /// <summary>
        /// Gets or sets the rect1.
        /// </summary>
        /// <value>
        /// The rect1.
        /// </value>
        public Rectangle Rect1
        {
            get { return this.rect; }
            set { this.rect = value; }
        }

        /// <summary>
        /// Brings to top.
        /// </summary>
        public void BringToTop()
        {
            this.TopMost = true;
        }

        /// <summary>
        /// Updates the form size.
        /// </summary>
        public void UpdateSize()
        {
            this.Size = new Size(this.BackgroundImage.Size.Width + 15, this.BackgroundImage.Size.Height + 40);
        }

        /// <summary>
        /// Updates the form.
        /// </summary>
        public void UpdateForm()
        {
            this.UpdateSize();
            this.CheckMode();
            this.BackgroundImage = this.dimage.ImageBitmap;
        }

        /// <summary>
        /// Updates the form.
        /// </summary>
        /// <param name="image">The image.</param>
        public void UpdateForm(Bitmap image)
        {
            this.dimage.ImageBitmap = image;
            this.BackgroundImage = this.dimage.ImageBitmap;
            this.UpdateForm();
        }

        /// <summary>
        /// Handles the MouseDown event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The PicForm_MouseDown instance containing the event data.</param>
        private void PicForm_MouseDown(object sender, MouseEventArgs e)
        {
            this.dimage.MyShaps.MouseDownAction(sender, e);
            if (mode == PicMode.Select)
            {
                this.dimage.RetriveImageArray();
                this.dimage.RetriveImageArray();
                this.rect = new Rectangle(e.X, e.Y, 0, 0);
            }

            this.Invalidate();
            this.cursorStartPos.X = e.X;
            this.cursorStartPos.Y = e.Y;
        }

        /// <summary>
        /// Handles the MouseMove event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The PicForm_MouseMove instance containing the event data.</param>
        private void PicForm_MouseMove(object sender, MouseEventArgs e)
        {
            this.dimage.MyShaps.MouseMoveAction(sender, e);
            if (mode == PicMode.Select)
            {
                if (e.Button == MouseButtons.Left)
                {
                    this.rect = new Rectangle(this.rect.Left, this.rect.Top, e.X - this.rect.Left, e.Y - this.rect.Top);
                    this.topLeft.X = this.rect.Left;
                    this.topLeft.Y = this.rect.Top;
                    this.downRight.X = e.X;
                    this.downRight.Y = e.Y;
                }
            }

            this.Invalidate();
            this.cursorCurrPos.X = e.X;
            this.cursorCurrPos.Y = e.Y;
        }

        /// <summary>
        /// Handles the Paint event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The PicForm_Paint instance containing the event data.</param>
        private void PicForm_Paint(object sender, PaintEventArgs e)
        {
            if (mode == PicMode.Select)
            {
                using (Pen pen = new Pen(Color.Red, 2))
                {
                    e.Graphics.DrawRectangle(pen, this.rect);
                }
            }

            // here redrawing ...            
            for (int i = 0; i < this.dimage.MyShaps.AllShapes.Count; i++)
            {
                // use the graphics object in "e" to draw
                this.dimage.MyShaps.AllShapes[i].Draw(e.Graphics);
            }

            if (this.dimage.MyShaps.TmpShape != null)
            {
                this.dimage.MyShaps.TmpShape.DrawForCreation(e.Graphics);
            }
        }

        /// <summary>
        /// Handles the Activated event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The PicForm_Activated instance containing the event data.</param>
        private void PicForm_Activated(object sender, EventArgs e)
        {
            Main.CurrImage = this.dimage.Id;
            this.CheckMode();
        }

        /// <summary>
        /// Checks the cursor.
        /// </summary>
        private void CheckCursor()
        {
            switch (curso)
            {
                case CursorType.Cross:
                    this.Cursor = System.Windows.Forms.Cursors.Cross;
                    break;
                default:
                    this.Cursor = System.Windows.Forms.Cursors.Default;
                    break;
            }
        }

        /// <summary>
        /// Checks the mode.
        /// </summary>
        private void CheckMode()
        {
            this.CheckCursor();
            switch (mode)
            {
                case PicMode.Select:
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Handles the BackgroundImageChanged event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The PicForm_BackgroundImageChanged instance containing the event data.</param>
        private void PicForm_BackgroundImageChanged(object sender, EventArgs e)
        {
            this.UpdateSize();
        }

        /// <summary>
        /// Handles the MouseUp event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void PicForm_MouseUp(object sender, MouseEventArgs e)
        {
            this.dimage.MyShaps.MouseUpAction(sender, e);
            if (mode == PicMode.Select)
            {
                this.rect.Size = new Size(new Point(0, 0));
                Thread t = null;
                int rowsPerThread = this.dimage.Height / Environment.ProcessorCount;
                Semaphore s = new Semaphore(1, 1000);
                int minHeight = 0, maxHeight = 0;
                for (int i = 1; i < Environment.ProcessorCount; i++)
                {
                    s.WaitOne();
                    minHeight = i * rowsPerThread;
                    maxHeight = (i + 1) * rowsPerThread;
                    if (i == (Environment.ProcessorCount - 1))
                    {
                        t = new Thread(delegate() { this.CroppingImageSizeThreading(s, minHeight, this.dimage.Height, this.dimage.ImageStructArray); });
                        t.Start();
                        break;
                    }

                    t = new Thread(delegate() { this.CroppingImageSizeThreading(s, minHeight, maxHeight, this.dimage.ImageStructArray); });
                    t.Start();
                }

                this.CroppingImageSizeThreading(s, 0, rowsPerThread, this.dimage.ImageStructArray);

                this.dimage.UpdateImage(this.dimage.ImageStructArray);
            }
            else
            {
                return;
            }
        }

        /// <summary>
        /// Croppings the image size threading.
        /// </summary>
        /// <param name="s">The s.</param>
        /// <param name="minHeight">Height of the min.</param>
        /// <param name="maxHeight">Height of the max.</param>
        /// <param name="image">The image.</param>
        private void CroppingImageSizeThreading(Semaphore s, int minHeight, int maxHeight, ImageStructure[,] image)
        {
            s.Release();
            for (int i = minHeight; i < maxHeight; i++)
            {
                for (int j = 0; j < this.dimage.Width; j++)
                {
                    if (j >= this.topLeft.X && j <= this.downRight.X && i >= this.topLeft.Y && i <= this.downRight.Y)
                    {
                        continue;
                    }

                    image[i, j].G = 0;
                    image[i, j].R = 0;
                }
            }
        }

        /// <summary>
        /// Handles the MouseLeave event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PicForm_MouseLeave(object sender, EventArgs e)
        {
            if (Owner != null)
            {
                Owner.Activate();
            }
        }

        /// <summary>
        /// Handles the MouseEnter event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PicForm_MouseEnter(object sender, EventArgs e)
        {
            // this.Activate();
        }

        /// <summary>
        /// Handles the Load event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PicForm_Load(object sender, EventArgs e)
        {
            return;
        }

        /// <summary>
        /// Handles the MouseClick event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void PicForm_MouseClick(object sender, MouseEventArgs e)
        {
            this.dimage.MyShaps.MouseClickAction(sender, e);
            this.Invalidate();
        }

        /// <summary>
        /// Handles the MouseDoubleClick event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void PicForm_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.dimage.MyShaps.MouseDoubleClickAction(sender, e);
            this.Invalidate();
        }

        /// <summary>
        /// Handles the FormClosed event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.FormClosedEventArgs"/> instance containing the event data.</param>
        private void PicForm_FormClosed(object sender, FormClosedEventArgs e)
        {
          //  DImage.DecreaseImagesCount();
           // Main.PicWindows.DropDownItems.RemoveByKey(this.dimage.Name);
           // Main.RemoveImageFromList(this.dimage.Id);

            // this.dimage.tab.RemoveTab();
          //  if (DImage.ImagesCount != 0)
          //  {
                // Main.CurrImage = Main.ImageList[0].Id;
          //  }
        }

        /// <summary>
        /// Handles the KeyPress event of the PicForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.KeyPressEventArgs"/> instance containing the event data.</param>
        private void PicForm_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 'D' || e.KeyChar == 'd')
            {
                this.dimage.MyShaps.AllShapes.Remove(this.dimage.MyShaps.SelectedShape);
            }
        }
    }
}